home *** CD-ROM | disk | FTP | other *** search
Oberon Text | 1995-06-30 | 26.4 KB | 706 lines | [TEXT/.Ob4] |
- Syntax10.Scn.Fnt
- Syntax10i.Scn.Fnt
- StampElems
- Alloc
- 21 Apr 95
- Syntax10b.Scn.Fnt
- MODULE Dialogs;
- (** extended version Markus Knasm
- ller 25.May.94 -
- IMPORT Display, Files, Modules, Oberon, TextFrames, TextPrinter, Texts, Types, Viewers;
- CONST
- ok* = 0; objectIsAlreadyInPanel* = 1; nameExists* = 2; objectNotFound* = 3;
- wrongInput* = 4; noPanelSelected* = 5; objectWouldOverlap* = 6; tooManyObjectsSelected* = 7;
- maxItems = 64;
- TYPE
- Object* = POINTER TO ObjectDesc;
- Panel* = POINTER TO PanelDesc;
- ObjectDesc* = RECORD
- next: Object;
- x, y, w, h: LONGINT;
- name-: ARRAY 16 OF CHAR; (** a panel wide unique name *)
- cmd-: ARRAY 32 OF CHAR; (** a command to be executed when the obj is changed *)
- par-: ARRAY 32 OF CHAR;
- (** the invoked commands can assume that Oberon.par.text contains the contest of these text items *)
- selected-: BOOLEAN; (** TRUE if the object is selected *)
- overlapping-: BOOLEAN; (** TRUE if the object may overlap others *)
- panel-: Panel; (** panel containing the object *)
- visible: BOOLEAN; (* TRUE if the object is visible *)
- END;
- PanelDesc* = RECORD
- cmd-: ARRAY 64 OF CHAR; (** cmd which initialies the dialog *)
- contents: Object;
- END;
- NotifyMsg* = RECORD(Display.FrameMsg)
- id*: INTEGER; (** 0 = restore, 1 = hide, 2 = markMenu, 3 = restore all *)
- obj*: Object; (** defined if id = 0 or id = 1 *)
- p*: Panel; (** defined if id = 2 or id = 3 *)
- END;
- dUnit*, pUnit*: LONGINT; (** for device independent coordinates *)
- res*: INTEGER; (** result code from last operation *)
- Edit*: PROCEDURE (obj: Object);
- Update*: PROCEDURE (obj: Object; p: Panel);
- cmdPanel*: Panel; (** panel from which the last command was called *)
- editPanel*: Panel; (** panel for editing the properties of an object *)
- editObject*: Object; (** object which could be edited by editPanel *)
- deInit*: Panel; (** panel representing DEInit.Dlg *)
- lastin*: Object; (** most recently inserted object *)
- w0: Texts.Writer;
- PROCEDURE^ (p: Panel) MarkMenu*;
- PROCEDURE^ (p: Panel) NamedObject* (name: ARRAY OF CHAR): Object;
- PROCEDURE^ (p: Panel) GetObjects* (x, y, w, h: INTEGER; VAR obArray: ARRAY OF Object; VAR nofelems: INTEGER);
- PROCEDURE^ (p: Panel) RestoreOverlapped (x, y, w, h: INTEGER; o: Object);
- PROCEDURE^ (p: Panel) RemoveSelections*;
- PROCEDURE (o: Object) Draw* (x, y: INTEGER; f: Display.Frame);
- (** abstract: displays the object at (x, y) in frame f *)
- END Draw ;
- PROCEDURE (o: Object) Copy* (VAR dup: Object);
- (** allocates dup and makes a deep copy of o. For calling this methode dup should be equal NIL *)
- BEGIN
- IF dup = NIL THEN NEW (dup) END;
- dup.x := o.x; dup.y := o.y; dup.w := o.w; dup.h := o.h; dup.name := o.name; dup.next := NIL;
- dup.cmd := o.cmd; dup.par := o.par; dup.selected := FALSE; dup.overlapping := o.overlapping; dup.panel := NIL;
- END Copy;
- PROCEDURE (o: Object) Print* (x, y: INTEGER);
- (** abstract: prints the object at printer coordinates (x, y) *)
- END Print;
- PROCEDURE (o: Object) Handle* (f: Display.Frame; VAR msg: Display.FrameMsg);
- (** abstract: handles messages which were sent to frame f *)
- END Handle;
- PROCEDURE (o: Object) Edit*;
- (** opens a dialog for editing the properties of the object *)
- BEGIN IF Edit # NIL THEN Edit (o) END
- END Edit;
- PROCEDURE (o: Object) Update* (p: Panel);
- (** sets the properties of the object to the values defined in the dialog p opened with Edit *)
- BEGIN IF Update # NIL THEN Update (o, p) END
- END Update;
- PROCEDURE (o: Object) Init*;
- (** initialies the object, should be called after allocating the object with NEW *)
- BEGIN o.selected := FALSE; o.panel := NIL; o.cmd[0] := 0X; o.par[0] := 0X; o.visible := TRUE;
- END Init;
- PROCEDURE (o: Object) GetDim* (VAR x, y, w, h: INTEGER);
- (** Gets x, y, width and height of object o for drawing *)
- BEGIN
- x := SHORT (o.x DIV dUnit); y := SHORT (o.y DIV dUnit);
- w := SHORT (o.w DIV dUnit); h := SHORT (o.h DIV dUnit);
- END GetDim;
- PROCEDURE (o: Object) GetPDim* (VAR x, y, w, h: INTEGER);
- (** Gets x, y, width and height of object o for printing *)
- BEGIN
- x := SHORT (o.x DIV pUnit); y := SHORT (o.y DIV pUnit);
- w := SHORT (o.w DIV pUnit); h := SHORT (o.h DIV pUnit);
- END GetPDim;
- PROCEDURE (o: Object) Load* (VAR r: Files.Rider);
- (** reads the object from rider r *)
- VAR name1: ARRAY 64 OF CHAR; cmd1, par1: ARRAY 64 OF CHAR;
- BEGIN
- o.Init; Files.ReadString (r, name1); COPY (name1, o.name);
- Files.ReadString (r, cmd1); COPY (cmd1, o.cmd);
- Files.ReadString (r, par1); COPY (par1, o.par);
- Files.ReadLInt (r, o.x); Files.ReadLInt (r, o.y); Files.ReadLInt (r, o.w);
- Files.ReadLInt (r, o.h); Files.ReadBool (r, o.overlapping)
- END Load;
- PROCEDURE (o: Object) Store* (VAR r: Files.Rider);
- (** writes the object to rider r *)
- BEGIN
- Files.WriteString (r, o.name); Files.WriteString (r, o.cmd); Files.WriteString (r, o.par); Files.WriteLInt (r, o.x);
- Files.WriteLInt (r, o.y); Files.WriteLInt (r, o.w); Files.WriteLInt (r, o.h); Files.WriteBool (r, o.overlapping)
- END Store;
- PROCEDURE (o: Object) CallCmd* (f: Display.Frame; v: Viewers.Viewer; t: Texts.Text);
- (** invokes the command obj.cmd *)
- VAR callres: INTEGER;
- BEGIN
- IF o.cmd[0] # 0X THEN
- Oberon.Par.frame := f; Oberon.Par.vwr := v; Oberon.Par.text := t; Oberon.Par.pos := 0;
- cmdPanel := o.panel; Oberon.Call (o.cmd, Oberon.Par, FALSE, callres)
- END
- END CallCmd;
- PROCEDURE (o: Object) SetCmd* (cmd: ARRAY OF CHAR);
- (** sets the command of the object to cmd *)
- BEGIN
- IF cmd # o.cmd THEN
- COPY (cmd, o.cmd);
- IF o.panel # NIL THEN o.panel.MarkMenu END
- END
- END SetCmd;
- PROCEDURE (o: Object) SetPar* (par: ARRAY OF CHAR);
- (** sets the command of the object to par *)
- BEGIN
- IF par # o.par THEN
- COPY (par, o.par);
- IF o.panel # NIL THEN o.panel.MarkMenu END
- END
- END SetPar;
- PROCEDURE (o: Object) Restore*;
- (** restores object o => redraws it *)
- VAR msg: NotifyMsg;
- BEGIN msg.id := 0; msg.obj := o; Viewers.Broadcast (msg); o.visible := TRUE
- END Restore;
- PROCEDURE (o: Object) SetName* (name: ARRAY OF CHAR);
- (** sets the name of the object to name, unless in the panel containing o already exists such a name *)
- BEGIN
- IF (o.panel = NIL) OR (name[0] = 0X) OR (o.panel.NamedObject (name) = NIL) OR (o.panel.NamedObject (name) = o) THEN
- IF o.name # name THEN
- COPY (name, o.name); res := ok;
- IF o.panel # NIL THEN
- o.panel.MarkMenu; o.Restore;
- END
- END
- ELSE res := nameExists
- END
- END SetName;
- PROCEDURE (o: Object) Hide*;
- (** removes object from screen, but not from panel *)
- VAR msg: NotifyMsg; ox, oy, ow, oh, nofelems, i: INTEGER; obArray: ARRAY 50 OF Object;
- BEGIN
- IF o.panel = NIL THEN RETURN END;
- msg.id := 1; msg.obj := o; Viewers.Broadcast (msg); o.visible := FALSE;
- IF o.overlapping THEN
- o.GetDim (ox, oy, ow, oh);
- o.panel.RestoreOverlapped (ox, oy, ow, oh, o);
- (*o.panel.GetObjects (ox, oy, ow, oh, obArray, nofelems); i := 0;
- WHILE i < nofelems DO
- IF obArray[i] # o THEN obArray[i].Restore END;
- INC (i)
- END *)
- END
- END Hide;
- PROCEDURE (o: Object) Select* ();
- (** selects o and displays it selected *)
- VAR x, y, w, h: INTEGER;
- BEGIN
- IF ~ o.selected THEN
- o.selected := TRUE; o.Hide;
- o.Restore
- END
- END Select;
- PROCEDURE (o: Object) UnSelect* ();
- (** unselects o and displays it unselected *)
- VAR x, y, w, h: INTEGER;
- BEGIN
- IF o.selected THEN
- o.selected := FALSE; o.Hide; o.Restore;
- END
- END UnSelect;
- PROCEDURE (o: Object) IsIn (x, y, w, h: INTEGER): BOOLEAN;
- VAR x0, y0, w0, h0: LONGINT;
- BEGIN
- x0 := x * dUnit; y0 := y * dUnit; w0 := w * dUnit; h0 := h * dUnit;
- IF ~ (y0 + h0 < o.y) THEN
- IF (y0 + h0 >= o.y) & (y0 + h0 <= o.y + o.h) &
- ~ (((x0 < o.x) & (x0 + w0 < o.x)) OR (x0 > o.x + o.w)) THEN
- RETURN TRUE
- END;
- IF (y0 + h0 > o.y + o.h) & (y0 <= o.y + o.h) &
- ~ (((x0 < o.x) & (x0 + w0 < o.x)) OR (x0 > o.x + o.w)) THEN
- RETURN TRUE
- END
- END;
- RETURN FALSE
- END IsIn;
- PROCEDURE (o: Object) IsOverlapped (x, y, w, h: INTEGER): BOOLEAN;
- VAR x0, y0 , w0, h0: LONGINT;
- BEGIN
- x0 := x * dUnit; y0 := y * dUnit; w0 := w * dUnit; h0 := h * dUnit;
- RETURN (o.x >= x0) & (o.y >= y0) & (o.x + o.w <= x0 + w0) & (o.y + o.h <= y0 + h0)
- END IsOverlapped;
- PROCEDURE (o: Object) IsOverlapping (p: Panel; x, y, w, h: LONGINT; sel: BOOLEAN): BOOLEAN;
- (* Returns TRUE if o with new dimensions x, y, w, h would overlapping another object of panel p.
- If sel then overlapping a selected object doesn`t matter. *)
- VAR o1: Object; b: BOOLEAN; hx, hy, hw, hh: LONGINT;
- BEGIN
- IF o.overlapping THEN RETURN FALSE END;
- o1 := p.contents;
- WHILE o1 # NIL DO
- IF (o1 # o) & ~ o1.overlapping & ~(o1.selected & sel) THEN
- IF (o1.y < y + h) & (o1.y + o1.h > y) & (o1.x < x + w) & (o1.x + o1.w > x) THEN RETURN TRUE END
- END;
- o1 := o1.next
- END;
- RETURN FALSE
- END IsOverlapping;
- PROCEDURE (o: Object) SetDim* (x, y, w, h: INTEGER; cond: BOOLEAN);
- (** Sets x, y, width and height of object o *)
- VAR ox, oy, ow, oh: LONGINT; ax, ay, aw, ah: INTEGER;
- BEGIN
- o.GetDim (ax, ay, aw, ah);
- ox := x * dUnit; oy := y * dUnit; ow := w * dUnit; oh := h * dUnit;
- IF ow < dUnit THEN ow := dUnit END; IF oh < dUnit THEN oh := dUnit END;
- IF o.panel = NIL THEN
- o.x := ox; o.y := oy; o.w := ow; o.h := oh; res := ok
- ELSIF ~ o.IsOverlapping (o.panel, ox, oy, ow, oh, cond) THEN
- IF ~ o.selected THEN o.panel.RemoveSelections END;
- o.Hide; o.x := ox; o.y := oy; o.w := ow; o.h := oh;
- o.Restore; o.panel.MarkMenu;
- o.panel.RestoreOverlapped (ax, ay, aw, ah, o); res := ok
- ELSE
- res := objectWouldOverlap
- END;
- END SetDim;
- PROCEDURE (o: Object) OverlappingObject* (): Object;
- (** returns the object overlapping this object *)
- VAR o1, ret: Object; x, y, w, h, w1, h1: INTEGER;
- BEGIN
- IF o.panel = NIL THEN RETURN NIL END;
- o1 := o.panel.contents; ret := NIL;
- WHILE o1 # NIL DO
- IF (o # o1) & (o1.overlapping) THEN
- o1.GetDim (x, y, w, h);
- IF o.IsIn (x, y, w, h) THEN
- IF (ret = NIL) THEN
- ret := o1
- ELSE
- ret.GetDim (x, y, w1, h1);
- IF w1 * h1 > w * h THEN ret := o1 END
- END;
- END
- END;
- o1 := o1.next;
- END;
- RETURN ret
- END OverlappingObject;
- PROCEDURE (p: Panel) RestoreOverlapped (x, y, w, h: INTEGER; o: Object);
- VAR o1: Object;
- PROCEDURE Redraw;
- BEGIN
- IF o1.selected THEN
- IF o1.visible THEN o1.Hide END;
- o1.Restore
- ELSE o1.Restore
- END
- END Redraw;
- BEGIN
- o1 := p.contents;
- WHILE o1 # NIL DO
- IF (o1 # o) & o1.overlapping & o1.visible & o1.IsIn (x, y, w, h) THEN Redraw END;
- o1 := o1.next
- END;
- IF o.overlapping THEN
- o1 := p.contents;
- WHILE o1 # NIL DO
- IF (o1 # o) & ~ o1.overlapping & o1.visible & o1.IsIn (x, y, w, h) THEN Redraw END;
- o1 := o1.next
- END
- END
- END RestoreOverlapped;
- PROCEDURE (p: Panel) SetCmd* (cmd: ARRAY OF CHAR);
- (** sets the command of the object to cmd *)
- BEGIN
- IF cmd # p.cmd THEN
- COPY (cmd, p.cmd);
- p.MarkMenu
- END
- END SetCmd;
- PROCEDURE (p: Panel) NamedObject* (name: ARRAY OF CHAR): Object;
- (** returns the object with name name *)
- VAR o: Object;
- BEGIN
- IF name = "" THEN RETURN NIL END;
- o := p.contents;
- WHILE (o # NIL) & (o.name # name) DO o := o.next END;
- RETURN o
- END NamedObject;
- PROCEDURE (p: Panel) Select* (x, y, w, h: INTEGER);
- (** selects all objects in p which are lying under the box specified by x, y, w, h *)
- VAR o: Object;
- BEGIN
- o := p.contents;
- WHILE o # NIL DO
- IF o.IsIn (x, y, w, h) THEN o.Select ELSE o.UnSelect END;
- o := o.next
- END
- END Select;
- PROCEDURE (p: Panel) GetObjects* (x, y, w, h: INTEGER; VAR obArray: ARRAY OF Object; VAR nofelems: INTEGER);
- (** gets all objects in p which are lying unter the box specified by x, y, w, h *)
- VAR o: Object;
- BEGIN
- nofelems := 0; o := p.contents;
- WHILE (o # NIL) & (nofelems < LEN (obArray)) DO
- IF o.IsIn (x, y, w, h) THEN obArray [nofelems] := o; INC (nofelems) END;
- o := o.next;
- END
- END GetObjects;
- PROCEDURE (p: Panel) MarkMenu*;
- (** marks the menu of the frames which are displaying p *)
- VAR msg: NotifyMsg;
- BEGIN msg.id := 2; msg.p := p; Viewers.Broadcast (msg);
- END MarkMenu;
- PROCEDURE (p: Panel) Restore*;
- (** restores the panel p => redraws it *)
- VAR msg: NotifyMsg;
- BEGIN msg.id := 3; msg.p := p; Viewers.Broadcast (msg)
- END Restore;
- PROCEDURE (p: Panel) Remove* (o: Object);
- (** removes object o of panel p *)
- VAR q, prev: Object;
- BEGIN
- q := p.contents;
- WHILE (q # NIL) & (q # o) DO prev := q; q := q.next END;
- IF q # NIL THEN
- q.Hide;
- IF q = p.contents THEN p.contents := q.next ELSE prev.next := q.next END;
- q.next := NIL; res := ok; p.MarkMenu
- ELSE
- res := objectNotFound
- END
- END Remove;
- PROCEDURE (p: Panel) RemoveObjects* (x, y, w, h: INTEGER);
- (** deletes all objects in p which are within x, y, w, h *)
- VAR o, next: Object;
- BEGIN
- o := p.contents;
- WHILE o # NIL DO
- next := o.next;
- IF o.IsIn (x, y, w, h) THEN p.Remove (o) END;
- o := next;
- END
- END RemoveObjects;
- PROCEDURE (p: Panel) Enumerate* (handle: PROCEDURE (obj: Object; VAR done: BOOLEAN));
- (** calls the procedure handle for every object of the panel *)
- VAR obj: Object; done: BOOLEAN;
- BEGIN
- done := FALSE; obj := p.contents;
- WHILE (obj # NIL) & ~ done DO handle (obj, done); obj := obj.next END
- END Enumerate;
- PROCEDURE (p:Panel) RemoveSelections* ();
- (** Unselects all objects *)
- VAR o: Object;
- BEGIN
- o := p.contents;
- WHILE o # NIL DO o.UnSelect (); o := o.next END;
- END RemoveSelections;
- PROCEDURE (p: Panel) Insert* (o: Object; ov: BOOLEAN);
- (** inserts object o in panel p *)
- VAR i, x0, j: INTEGER; a, b: ARRAY 15 OF CHAR;
- BEGIN
- o.overlapping := ov;
- IF ~ o.IsOverlapping(p, o.x, o.y, o.w, o.h, FALSE) THEN
- IF p.NamedObject (o.name) = NIL THEN
- o.panel := p; o.next := p.contents; p.contents := o;
- o.Restore; o.panel.MarkMenu; lastin := o;
- ELSE res := nameExists
- END
- ELSE res := objectWouldOverlap
- END
- END Insert;
- PROCEDURE (p: Panel) Copy* (): Panel;
- (** returns a deep copy of p *)
- VAR copy: Panel; o, o1: Object;
- BEGIN
- NEW (copy); o := p.contents; copy.cmd := p.cmd;
- WHILE o # NIL DO
- o1 := NIL; o.Copy (o1); copy.Insert (o1, o.overlapping); o := o.next;
- END;
- RETURN copy
- END Copy;
- PROCEDURE (p: Panel) NofSelObjects* (): INTEGER;
- (** returns the number of selected objects in p *)
- VAR o: Object; count: INTEGER;
- BEGIN
- o := p.contents; count := 0;
- WHILE o # NIL DO
- IF o.selected THEN INC (count) END;
- o := o.next
- END;
- RETURN (count)
- END NofSelObjects;
- PROCEDURE (p: Panel) ThisObject* (x, y: INTEGER): Object;
- (** returns the object including the coordinates x and y; first it tries to get a not overlapping object *)
- VAR o1, o: Object; x0, y0: LONGINT;
- BEGIN
- o := p.contents; o1:= NIL;
- x0 := x * dUnit; y0 := y * dUnit;
- WHILE o # NIL DO
- IF (x0 >= o.x) & (x0 < o.x + o.w) & (y0 >= o.y) & (y0 < o.y + o.h) THEN
- IF (o1 = NIL) OR ~ o.overlapping THEN o1 := o END
- END;
- o := o.next
- END;
- RETURN o1
- END ThisObject;
- PROCEDURE (p: Panel) Draw* (x, y: INTEGER; f: Display.Frame);
- (** draws the panel at (x, y) in frame f *)
- VAR o: Object; ox, oy, ow, oh: INTEGER;
- BEGIN
- o := p.contents;
- WHILE o # NIL DO
- IF o.overlapping THEN o.GetDim (ox, oy, ow, oh); o.Draw (x + ox, y + oy , f) END;
- o := o.next
- END;
- o := p.contents;
- WHILE o # NIL DO
- IF ~ o.overlapping THEN o.GetDim (ox, oy, ow, oh); o.Draw (x + ox, y + oy , f) END;
- o := o.next
- END
- END Draw;
- PROCEDURE (p: Panel) Print* (x, y: INTEGER);
- (** prints the panel at printer coordinates (x, y) *)
- VAR o: Object; ox, oy, ow, oh: INTEGER;
- BEGIN
- o := p.contents;
- WHILE o # NIL DO
- o.GetPDim (ox, oy, ow, oh); o.Print (x + ox, y + oy); o := o.next
- END
- END Print;
- PROCEDURE (p: Panel) Load* (VAR r: Files.Rider);
- (** reads the panel from rider r *)
- VAR cnt, end1, end2, h: INTEGER; o, prev: Object; module: Modules.ModuleName; name: ARRAY 32 OF CHAR;
- tab1: ARRAY maxItems OF Modules.ModuleName; tab2: ARRAY maxItems OF ARRAY 32 OF CHAR;
- pos: LONGINT;
- BEGIN
- p.contents := NIL; prev := NIL; Files.ReadInt(r, cnt); COPY ("", p.cmd); end1 := 0; end2 := 0;
- WHILE cnt # 0 DO DEC (cnt);
- pos := Files.Pos (r); Files.ReadInt (r, h);
- IF h < end1 THEN module := tab1[h]
- ELSE Files.Set (r, Files.Base (r), pos); Files.ReadString (r, module); tab1[end1] := module; INC (end1)
- END;
- pos := Files.Pos (r); Files.ReadInt (r, h);
- IF h < end2 THEN COPY (tab2[h], name)
- ELSE Files.Set (r, Files.Base (r), pos); Files.ReadString (r, name); COPY (name, tab2[end2]); INC (end2)
- END;
- Types.NewObj (o, Types.This (Modules.ThisMod (module), name)); ASSERT (o # NIL);
- o.Load (r); o.panel := p;
- IF prev # NIL THEN prev.next := o ELSE p.contents := o END;
- prev := o
- END;
- Files.ReadString (r, p.cmd);
- p.Restore ()
- END Load;
- PROCEDURE (p: Panel) Store* (VAR r: Files.Rider);
- (** stores the panel from rider r *)
- VAR cnt, end1, end2, i: INTEGER; o: Object; type: Types.Type; cond: BOOLEAN;
- tab1, tab2: ARRAY maxItems OF ARRAY 32 OF CHAR;
- BEGIN
- o := p.contents; cnt := 0; end1 := 0; end2 := 0;
- WHILE o # NIL DO INC (cnt); o := o.next END;
- Files.WriteInt (r, cnt); o := p.contents;
- WHILE o # NIL DO
- type := Types.TypeOf (o); cond := FALSE;
- FOR i := 0 TO end1 -1 DO
- IF tab1[i] = type.module.name THEN Files.WriteInt (r, i); cond := TRUE END;
- END;
- IF ~cond THEN Files.WriteString (r, type.module.name); COPY (type.module.name, tab1[end1]); INC (end1) END;
- cond := FALSE;
- FOR i := 0 TO end2 -1 DO
- IF tab2[i] = type.name THEN Files.WriteInt (r, i); cond := TRUE END;
- END;
- IF ~cond THEN Files.WriteString (r, type.name); COPY (type.name, tab2[end2]); INC (end2) END;
- o.Store (r); o := o.next
- END;
- Files.WriteString (r, p.cmd)
- END Store;
- PROCEDURE (p: Panel) Contains* (o: Object): BOOLEAN;
- (** returns TRUE if the panel contains o *)
- VAR o1: Object;
- BEGIN
- o1 := p.contents;
- WHILE o1 # NIL DO
- IF o1 = o THEN RETURN TRUE END;
- o1 := o1.next
- END;
- RETURN FALSE
- END Contains;
- PROCEDURE (p: Panel) MoveSelected* (dx, dy: INTEGER);
- (** moves all selected objects around dx and dy *)
- VAR
- o: Object; ov: BOOLEAN; msg: NotifyMsg;
- ox, oy, ow, oh, i, nofelems: INTEGER; dx0, dy0: LONGINT;
- obArray: ARRAY 50 OF Object;
- BEGIN
- IF p.NofSelObjects () = 0 THEN res := ok; RETURN END;
- o := p.contents; ov := FALSE;
- dx0 := dx * dUnit; dy0 := dy * dUnit;
- WHILE (o # NIL) & (~ ov) DO
- IF o.selected THEN ov := o.IsOverlapping (p, o.x + dx0, o.y + dy0, o.w, o.h, TRUE) END;
- o := o.next
- END;
- o := p.contents;
- IF ~ ov THEN
- WHILE o # NIL DO
- IF o.selected THEN
- msg.id := 1; msg.obj := o; Viewers.Broadcast (msg);
- o.GetDim (ox, oy, ow, oh); p.GetObjects (ox, oy, ow, oh, obArray, nofelems); i := 0;
- WHILE i < nofelems DO
- IF (~ obArray[i].selected) THEN obArray[i].Restore END;
- INC (i)
- END
- END;
- o := o.next
- END;
- o := p.contents;
- WHILE o # NIL DO
- IF o.selected THEN o.x := o.x + dx0; o.y := o.y + dy0 END;
- o := o.next
- END;
- o := p.contents;
- WHILE o # NIL DO
- IF o.selected & o.overlapping THEN o.Restore END;
- o := o.next
- END;
- o := p.contents;
- WHILE o # NIL DO
- IF o.selected & ~ o.overlapping THEN o.Restore END;
- o := o.next
- END;
- res := ok; p.MarkMenu
- ELSE
- res := objectWouldOverlap
- END
- END MoveSelected;
- PROCEDURE (p: Panel) ChangeDistance (dir: CHAR);
- VAR sort: ARRAY 50 OF Object; n, i: INTEGER; o: Object; d: LONGINT;
- PROCEDURE Greater (o1, o2: Object): BOOLEAN;
- BEGIN
- IF (dir = "R") OR (dir = "L") THEN RETURN o1.x > o2.x ELSE RETURN o1.y > o2.y END
- END Greater;
- BEGIN
- (* ---- sort objects *)
- o := p.contents; n := 0;
- WHILE o # NIL DO
- IF o.selected THEN
- i := n - 1;
- WHILE (i >= 0) & Greater (sort [i], o) DO
- sort [i + 1] := sort [i]; DEC (i)
- END;
- sort [i + 1] := o; INC (n)
- END;
- o := o.next
- END;
- (* ---- calculate distance *)
- d := 0;
- IF (dir = "R") OR (dir = "L") THEN
- FOR i := 0 TO n - 2 DO d := d + sort[i].x - sort[i + 1].x - sort[i + 1].w END
- ELSE
- FOR i := 0 TO n - 2 DO d := d + sort[i].y - sort[i + 1].y - sort[i + 1].h END
- END;
- d := d DIV (n - 1);
- (* ---- change distance *)
- IF (dir = "R") OR (dir = "L") THEN
- FOR i := 0 TO n - 2 DO sort[i + 1].x := sort[i].x - sort[i + 1].w - d END
- ELSIF (dir = "U") OR (dir = "D") THEN
- FOR i := 0 TO n - 2 DO sort[i + 1].y := sort[i].y - sort[i + 1].h - d END
- END
- END ChangeDistance;
- PROCEDURE (p: Panel) AlignTest (dir: CHAR; x: LONGINT): BOOLEAN;
- (* returns TRUE if Align with parameters dir and x is not possible *)
- VAR p2: Panel; o: Object;
- BEGIN
- p2 := p.Copy (); o := p2.contents;
- WHILE o # NIL DO
- IF o.selected THEN
- IF dir = "R" THEN o.x := x - o.w
- ELSIF dir = "L" THEN o.x := x
- ELSIF dir = "U" THEN o.y := x - o.h
- ELSIF dir = "D" THEN o.y := x
- END;
- END;
- o := o.next
- END;
- o := p2.contents;
- WHILE o # NIL DO
- IF o.IsOverlapping (p2, o.x, o.y, o.w, o.h, FALSE) THEN RETURN TRUE END;
- o := o.next
- END;
- RETURN FALSE
- END AlignTest;
- PROCEDURE (p: Panel) RegulateDistanceTest (dir: CHAR): BOOLEAN;
- (* returns TRUE if RegulateDistance with parameters dir and x is not possible *)
- VAR p2: Panel; o: Object;
- BEGIN
- p2 := p.Copy (); p2.ChangeDistance (dir); o := p2.contents;
- WHILE o # NIL DO
- IF o.IsOverlapping (p2, o.x, o.y, o.w, o.h, FALSE) THEN RETURN TRUE END;
- o := o.next
- END;
- RETURN FALSE
- END RegulateDistanceTest;
- PROCEDURE (p: Panel) AlignSelected* (dir: CHAR);
- (** aligns the selected objects according to dir (Right, Left, Up or Down) *)
- VAR o: Object; x: LONGINT;
- PROCEDURE Max;
- BEGIN
- IF dir = "R" THEN IF o.x + o.w > x THEN x := o.x + o.w END
- ELSIF dir = "L" THEN IF o.x < x THEN x := o.x END
- ELSIF dir = "U" THEN IF o.y + o.h > x THEN x := o.y + o.h END
- ELSIF dir = "D" THEN IF o.y < x THEN x := o.y END
- END
- END Max;
- BEGIN
- IF (dir # "R") & (dir # "L") & (dir # "U") & (dir # "D") THEN res := wrongInput; RETURN END;
- IF p.NofSelObjects() = 0 THEN res:= ok; RETURN END;
- o := p.contents;
- IF (dir = "R") OR (dir = "D") THEN
- x := 0
- ELSIF (dir = "L") THEN
- x := MAX (LONGINT)
- ELSE
- x := MIN (LONGINT);
- END;
- WHILE o # NIL DO
- IF o.selected THEN Max END;
- o := o.next
- END;
- IF ~ p.AlignTest (dir, x) THEN
- o := p.contents;
- WHILE o# NIL DO
- IF o.selected THEN
- IF dir = "R" THEN o.x := x - o.w
- ELSIF dir = "L" THEN o.x := x
- ELSIF dir = "U" THEN o.y := x - o.h
- ELSIF dir = "D" THEN o.y := x
- END
- END;
- o := o.next;
- END;
- p.Restore; res := ok; p.MarkMenu
- ELSE
- res := objectWouldOverlap
- END
- END AlignSelected;
- PROCEDURE (p: Panel) RegulateDistance* (dir: CHAR);
- (** aligns the selected objects along the direction dir such that they are equidistant *)
- BEGIN
- IF (dir # "R") & (dir # "L") & (dir # "U") & (dir # "D") THEN res := wrongInput; RETURN END;
- IF p.NofSelObjects () > 50 THEN res := tooManyObjectsSelected; RETURN END;
- IF p.NofSelObjects () < 3 THEN res := ok; RETURN END;
- IF ~ p.RegulateDistanceTest (dir) THEN
- p.ChangeDistance (dir);
- p.Restore (); res := ok; p.MarkMenu
- ELSE
- res := objectWouldOverlap
- END
- END RegulateDistance;
- PROCEDURE (p: Panel) Broadcast* (f: Display.Frame; VAR m: Display.FrameMsg);
- (** sends the message m to all objects in the panel p which is displayed in frame f *)
- VAR o, o1: Object;
- BEGIN
- o := p.contents;
- WHILE o # NIL DO
- o.Handle (f, m); o := o.next;
- END
- END Broadcast;
- PROCEDURE Error* (name: ARRAY OF CHAR);
- (** writes an error message to the log viewer *)
- BEGIN
- Texts.WriteString (w0, name);
- IF res = objectIsAlreadyInPanel THEN Texts.WriteString (w0, " Error 1: Object is already in Panel")
- ELSIF res = nameExists THEN Texts.WriteString (w0, " Error 2: Name exists")
- ELSIF res = objectNotFound THEN Texts.WriteString (w0, " Error 3: Object not found")
- ELSIF res = wrongInput THEN Texts.WriteString (w0, " Error 4: Wrong input")
- ELSIF res = noPanelSelected THEN Texts.WriteString (w0, "Error 5: No panel selected")
- ELSIF res = objectWouldOverlap THEN Texts.WriteString
- (w0, " Error 6: Object would overlap another object")
- ELSIF res = tooManyObjectsSelected THEN Texts.WriteString
- (w0, " Error 7: Too many objects selected")
- ELSE Texts.WriteInt (w0, res, 5)
- END;
- Texts.WriteLn (w0);
- Texts.Append (Oberon.Log, w0.buf)
- END Error;
- BEGIN
- dUnit := TextFrames.Unit; pUnit := TextPrinter.Unit; Edit := NIL; Update := NIL;
- res := ok; editPanel := NIL; cmdPanel := NIL; editObject := NIL; lastin := NIL;
- Texts.OpenWriter (w0);
- END Dialogs.
-